﻿using Abp.Domain.Repositories;
using MyCompanyName.AbpZeroTemplate.Prm.Project;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Threading.Tasks;
using Abp.AutoMapper;
using MyCompanyName.AbpZeroTemplate.Prm.Admin.Dto;
using Abp.Application.Services.Dto;
using System.Dynamic;
using MyCompanyName.AbpZeroTemplate.Prm.Authorization;

namespace MyCompanyName.AbpZeroTemplate.Prm.Admin
{
    public class ProjectRoleAppService : AbpZeroTemplateAppServiceBase, IProjectRoleAppService
    {
        private readonly ProjectManager _projectManager;
        IRepository<ProjectRoleInfo, int> projectRoleRepository;
        IRepository<ProjectRoleFunctionActions, int> projectRoleFunctionActionsRepository;
        IRepository<ProjectRoleDocmentActions, int> projectRoleDocmentActionsRepository;

        private readonly IRepository<DocumentType, int> documentTypeRepository;

        public ProjectRoleAppService(IRepository<ProjectRoleInfo, int> _projectRoleRepository,
            IRepository<ProjectRoleFunctionActions, int> _projectRoleFunctionActionsRepository,
            IRepository<ProjectRoleDocmentActions, int> _projectRoleDocmentActionsRepository,
            ProjectManager projectManager,
            IRepository<DocumentType, int> _documentTypeRepository)
        {
            projectRoleRepository = _projectRoleRepository;
            _projectManager = projectManager;
            projectRoleFunctionActionsRepository = _projectRoleFunctionActionsRepository;
            projectRoleDocmentActionsRepository = _projectRoleDocmentActionsRepository;
            documentTypeRepository = _documentTypeRepository;
        }
        public async Task<List<Dto.ProjectRoleOutPut>> GetAll()
        {
            var projectRoles = await projectRoleRepository.GetAll().ToListAsync();


            var subListDtos = projectRoles.MapTo<List<ProjectRoleOutPut>>();

            return subListDtos;
        }


        public async Task<List<dynamic>> GetRoleAuth()
        {
            List<dynamic> result = new List<dynamic>();

            var projectRoles = await projectRoleRepository.GetAll().ToListAsync();

            foreach (var item in Enum.GetValues(typeof(ProjectFunctions)))
            {
                dynamic dy = new ExpandoObject();
                dy.ProjectAuth = item.ToString();
                foreach (var role in projectRoles)
                {
                    ((IDictionary<string, object>)dy).Add(role.RoleName, HasRoleAction(role.Id, (ProjectFunctions)item));
                }
                result.Add(dy);
            }
            return result;
        }





        public bool HasRoleAction(int roleId, ProjectFunctions permission)
        {
            var hasAuth = projectRoleFunctionActionsRepository.GetAll().Where(x => x.ProjectRoleId == roleId && x.Permission == permission).Any();
            return hasAuth;
        }


        public List<ProjectRoleOutPut> GetPermissionRoles(ProjectFunctions permission)
        {
            var roleIds = projectRoleFunctionActionsRepository.GetAll().Where(x => x.Permission == permission).Select(x => x.ProjectRoleId);
            var roles = projectRoleRepository.GetAll().Where(x => roleIds.Contains(x.Id)).MapTo<List<ProjectRoleOutPut>>();

            return roles;
        }



        public async Task SetRoleAuth(SetProjectRoleAuthInPut input)
        {
            projectRoleFunctionActionsRepository.Delete(x => x.Id > 0);
            var projectRoles = await projectRoleRepository.GetAll().ToListAsync();
            foreach (var item in input.records)
            {
                var permission = (ProjectFunctions)Enum.Parse(typeof(ProjectFunctions), item["projectAuth"].Value);
                foreach (var r in projectRoles)
                {
                    var role = item[r.RoleName.ToLower()];
                    if (role != null && role.Value)
                    {
                        projectRoleFunctionActionsRepository.Insert(new ProjectRoleFunctionActions()
                        {
                            Permission = permission,
                            ProjectRoleId = r.Id
                        });
                    }
                }
            }
        }


        public bool HasRoleDocumentAction(int roleId, int typeId, DocmentFunctions permission)
        {
            var hasAuth = projectRoleDocmentActionsRepository.GetAll().Where(x => x.ProjectRoleId == roleId && x.DocTypeId == typeId && x.Permission == permission).Any();
            return hasAuth;
        }
        public async Task<List<dynamic>> GetRoleDocumentAuth(int projectRoleId)
        {
            List<dynamic> result = new List<dynamic>();

            var types = await documentTypeRepository.GetAll().Where(x => x.IsDeleted == false && x.IsEnabled).ToListAsync();

            foreach (var item in Enum.GetValues(typeof(DocmentFunctions)))
            {
                dynamic dy = new ExpandoObject();
                dy.DocumentAuth = item.ToString();
                foreach (var type in types)
                {
                    ((IDictionary<string, object>)dy).Add((type.Name + type.Id).ToLower(), HasRoleDocumentAction(projectRoleId, type.Id, (DocmentFunctions)item));
                }
                result.Add(dy);
            }
            return result;
        }


        public async Task SetRoleDocumentAuth(SetProjectRoleAuthInPut input)
        {
            projectRoleDocmentActionsRepository.Delete(x => x.ProjectRoleId == input.ProjectRoleId);

            var types = await documentTypeRepository.GetAll().Where(x=>x.IsEnabled&&!x.IsDeleted).ToListAsync();
            foreach (var item in input.records)
            {
                var permission = (DocmentFunctions)Enum.Parse(typeof(DocmentFunctions), item["documentAuth"].Value);
                foreach (var r in types)
                {
                    var t = item[(r.Name + r.Id).ToLower()];
                    if (t != null && t.Value)
                    {
                        projectRoleDocmentActionsRepository.Insert(new ProjectRoleDocmentActions()
                        {
                            Permission = permission,
                            ProjectRoleId = input.ProjectRoleId,
                            DocTypeId = r.Id
                        });
                    }
                }
            }
        }


        public async Task EditRole(EditProjectRoleInPut input)
        {
            var role = new ProjectRoleInfo();
            if (input.Id > 0)
            {
                role = await projectRoleRepository.GetAsync(input.Id);
            }
            else
            {
                await projectRoleRepository.InsertAsync(role);
            }
            role.Sortfactor = input.Sortfactor;
            role.RoleName = input.RoleName;
            role.Description = input.Description;
        }


        public async Task Remove(int projectRoleId)
        {
            var teamCount = _projectManager.projectTeamRepository.GetAll().Count(x => x.ProjectRoleId == projectRoleId);
            if (teamCount > 0)
            {
                throw new Abp.UI.UserFriendlyException("系统提示", "存在引用无法删除");
            }
            await projectRoleFunctionActionsRepository.DeleteAsync(x => x.Id == projectRoleId);
            await projectRoleDocmentActionsRepository.DeleteAsync(x => x.Id == projectRoleId);
            await projectRoleRepository.DeleteAsync(x => x.Id == projectRoleId);
        }
    }
}
